#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "types.h"
#include "params.h"
#include "preproc.h"

#define MIN_EXCLINESZ 64 //codeline lnstr额外增加大小 
#define ASSERT(fmt,arg...) {printf ("Preprocessor:");printf(#fmt,##arg);exit(EXIT_FAILURE);}

int
line_valid (char * line) {
    while (*line == ' ') line++;
    if (*line == '\n') return 0;
    if (*line == 0) return 0;
    if (*line == '#') return 0;
    return 1;
}

struct codeline *
preprocess(const char * file) {
    FILE * fp;
    char * line; // 读取的line
    char * lnstr; // 将附加到codeline上
    struct codeline clhead; 
    struct codeline * cl, * prevcl; // 当前codeline和先前codeline
    long unsigned int n; // 读取空间大小
    uint ln; // 行数
    int64 nread; // 读取字符数
    uint tknum; // 行内token数
    ln = 1; // 从第一行开始
    fp = fopen (file, "r"); 
    prevcl = &clhead; //先前codeline
    while ((nread = getline (&line,&n,fp)) != -1) {
        if (!line_valid (line)) {
            ln++;
            continue; // 检测当前行是否有效
        }
        cl = (struct codeline *) malloc (sizeof (struct codeline)); // 分配当前codeline
        bzero (cl, sizeof (struct codeline));
        lnstr = (char*) malloc (nread+MIN_EXCLINESZ); // 分配原行空间
        if (!lnstr || !cl) ASSERT ("内存不足");
        char * clptr = lnstr; // codeline lnstr指针
        char * lnptr = line; // 原行指针
        char prev = 0; // 上一个字符
        tknum = 0;
        while ((*lnptr!='\n') && (lnptr-line<nread)) {
            if (prev == 0 && *lnptr == ' ')  // 连续空格
                goto cont;
            if (*lnptr == '#') { //注释
                break;
            }
            if (*lnptr == ' ') {
                prev = 0;
                *clptr = 0;
                clptr++;
                goto cont;
            } else if (*lnptr == ',') { // 算一个token
                if (prev == 0) { // 前面是空格
                    *clptr = ',';
                } else { // 前面不是空格
                    *clptr = 0;
                    clptr++; // 添加空格
                    *clptr = ',';
                }
                tknum++;
                prev = ',';
                clptr++;
            } else {
                if (prev == 0)
                    tknum++;
                prev = *lnptr;
                *clptr = *lnptr;
                clptr++;
            }
            cont:
            lnptr++;
        }
        *clptr = 0;
        cl->lnstr = lnstr;
        cl->next = NULL;
        cl->tknum = tknum;
        cl->ln = ln;
        prevcl->next = cl;
        prevcl = cl;
        ln++;
    }
    prevcl->next = NULL;
    fclose (fp);
    return clhead.next;
}